package com.ruan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruan.common.Code;
import com.ruan.common.Result;
import com.ruan.mapper.*;
import com.ruan.pojo.*;
import com.ruan.service.EmployeeLeaveService;
import com.ruan.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class EmployeeLeaveServiceImpl extends ServiceImpl<EmployeeLeaveMapper, EmployeeLeave> implements EmployeeLeaveService {

    @Autowired
    private EmployeeLeaveMapper employeeLeaveMapper;

    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private LeaveTypeMapper leaveTypeMapper;

    @Autowired
    private OnDutyMapper onDutyMapper;

    @Autowired
    private BusinessTripMapper tripMapper;


    /**
     * 获得待审核请假列表
     * @return
     */
    @Override
    public List<EmployeeLeave> getAudit() {

        LambdaQueryWrapper<EmployeeLeave> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeLeave::getStatus,"待审核");
        List<EmployeeLeave> employeeLeaves = employeeLeaveMapper.selectList(queryWrapper);
        return employeeLeaves;
    }


    //同意请假申请
    @Override
    public void agreed(Integer id,Integer adminId) {
        EmployeeLeave employeeLeave = employeeLeaveMapper.selectById(id);
        employeeLeave.setStatus("同意");
        Admin admin = adminMapper.selectById(adminId);
        employeeLeave.setApprover(admin.getUsername());
        employeeLeaveMapper.updateById(employeeLeave);

        Date startTime = employeeLeave.getStartTime();
        Date endTime = employeeLeave.getEndTime();
        Long employeeId = employeeLeave.getEmployeeId();
        Integer leaveDay = employeeLeave.getDay();
//同步员工出勤onDuty状态（请假/旷工/正常/出差/迟到/早退）
        //如果请假开始时间和结束时间相同，创建一个新的出勤记录表示员工请假状态。
        if (startTime.equals(endTime)){
            OnDuty onDuty = new OnDuty();
            onDuty.setEmployeeId(employeeLeave.getEmployeeId());
            onDuty.setDepartmentId(employeeLeave.getDepartmentId());
            onDuty.setStatus("请假");
            onDuty.setDay(startTime);
            onDutyMapper.insert(onDuty);
        }else {//如果请假开始时间和结束时间不同，根据请假期间的每一天，更新或创建出勤记录表示员工请假状态。
            //根据请假开始时间和请假天数，生成请假期间的日期列表
            //4-20 4-21 4-22
            //获取一个表示当前日期和时间的Calendar对象
            Calendar calendar =Calendar.getInstance();
            calendar.setTime(startTime);
            List<Date> dateList = new ArrayList<>();
            dateList.add(startTime);
//逐步增加日期，直到达到指定的leaveDay，并将这些日期存储在dateList列表中。
            for (int i = 1; i < leaveDay; i++) {
                //将当前日期的星期几增加1天。这意味着它会将当前日期增加到下一个星期的相同星期几。
                calendar.add(Calendar.DAY_OF_WEEK,1);
//在计算日期时，应该使用Calendar.DAY_OF_MONTH而不是Calendar.DAY_OF_WEEK来增加日期。??
                Date day = new Date(calendar.getTime().getTime());
                dateList.add(day);
            }
            for (Date day : dateList) {
                LambdaQueryWrapper<OnDuty> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(OnDuty::getDay,day);
                queryWrapper.eq(OnDuty::getEmployeeId,employeeId);
                //如果能查到打卡的记录。依然设为请假（打卡上班之后依然请假）
                OnDuty onDutySelect = onDutyMapper.selectOne(queryWrapper);
                if (onDutySelect!=null){
                    onDutySelect.setStatus("请假");
                    onDutyMapper.updateById(onDutySelect);
                }
                OnDuty onDuty = new OnDuty();
                onDuty.setEmployeeId(employeeLeave.getEmployeeId());
                onDuty.setDepartmentId(employeeLeave.getDepartmentId());
                onDuty.setStatus("请假");//这期间的每一天都设为请假
                onDuty.setDay(day);
                onDutyMapper.insert(onDuty);
            }
        }
    }


   //驳回请假申请
    @Override
    public void refuse(Integer id,Integer adminId) {
        EmployeeLeave employeeLeave = employeeLeaveMapper.selectById(id);
        employeeLeave.setStatus("驳回");
        Admin admin = adminMapper.selectById(adminId);
        employeeLeave.setApprover(admin.getUsername());
        employeeLeaveMapper.updateById(employeeLeave);
    }


    //获取启用中的请假事由列表
    @Override
    public List<LeaveType> getUsingLeaveType() {
        LambdaQueryWrapper<LeaveType> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LeaveType::getStatus,"启用");
        List<LeaveType> leaveTypeList = leaveTypeMapper.selectList(queryWrapper);
        return leaveTypeList;
    }

    /**
     * 员工申请请假
     * @param employeeLeave 请假记录
     * @return
     */
    @Override
    public Result appForLeave(EmployeeLeave employeeLeave) {

        Date startTime = employeeLeave.getStartTime();
        Date endTime = employeeLeave.getEndTime();
        Long employeeId = employeeLeave.getEmployeeId();

        LambdaQueryWrapper<BusinessTrip> tripWrapper = new LambdaQueryWrapper<>();
        tripWrapper.eq(BusinessTrip::getEmployeeId,employeeId);
        tripWrapper.between(BusinessTrip::getLeaveTime,startTime,endTime)
                .or().between(BusinessTrip::getBackTime,startTime,endTime);
        List<BusinessTrip> businessTripList = tripMapper.selectList(tripWrapper);
        if (businessTripList.size()>0){
            return new Result(Code.SAVE_ERR,"该时间段您已申请出差！");
        }

        employeeLeave.setSubmitTime(new java.util.Date());
        java.util.Date submitTime = employeeLeave.getSubmitTime();

        Date date = new Date(submitTime.getTime());
        Integer leaveDay1 = DateUtils.getLeaveDay(date, startTime);

        if (leaveDay1<=1){
            return new Result(Code.SAVE_ERR,"请至少提前1天申请请假！");
        }

        LambdaQueryWrapper<EmployeeLeave> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EmployeeLeave::getEmployeeId,employeeId);
        queryWrapper.between(EmployeeLeave::getStartTime,startTime,endTime).
                or().between(EmployeeLeave::getEndTime,startTime,endTime);
        List<EmployeeLeave> employeeLeaveList = employeeLeaveMapper.selectList(queryWrapper);
        if (employeeLeaveList.size()>0){
            return new Result(Code.SAVE_ERR,"此时间段内您已申请请假！");
        }

        Integer leaveDay = DateUtils.getLeaveDay(startTime, endTime);
        if (leaveDay>=1){
            employeeLeave.setStatus("待审核");
            employeeLeave.setDay(leaveDay);
            employeeLeaveMapper.insert(employeeLeave);

            return new Result(Code.SAVE_OK,"申请请假成功！");
        }else {
            return new Result(Code.SAVE_ERR,"申请请假失败，请检查日期！");
        }

    }

    /**
     * 分页+条件 员工获取个人请假记录
     * @param currentPage 当前页
     * @param pageSize 每页最大数
     * @param querySelfAttendanceCondition 搜索条件
     * @return
     */
    @Override
    public IPage<EmployeeLeave> getSelfLeave(int currentPage,
                                             int pageSize,
                                             QuerySelfAttendanceCondition querySelfAttendanceCondition) {

        Date month = querySelfAttendanceCondition.getMonth();//2023-2-1
        IPage<EmployeeLeave> iPage=new Page<>(currentPage,pageSize);
        QueryWrapper<EmployeeLeave> queryWrapper = new QueryWrapper<>();
        //如果 querySelfAttendanceCondition.getStatus() 的返回值不为 null，
        // 则会添加一个模糊查询条件，查询字段为 status，
        // 查询值为 querySelfAttendanceCondition.getStatus() 的返回值。
        queryWrapper.like(querySelfAttendanceCondition.getStatus()!=null,
                "status", querySelfAttendanceCondition.getStatus());
//
        LambdaQueryWrapper<Employee> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.like(Employee::getPhone, querySelfAttendanceCondition.getPhone());
        List<Employee> employeeList = employeeMapper.selectList(queryWrapper1);

        List<Long> employeeIds = employeeList.stream().map(Employee::getId).collect(Collectors.toList());
        queryWrapper.in("employee_id", employeeIds);//是QueryWrapper的技术语句

//        queryWrapper.like("phone", querySelfAttendanceCondition.getPhone());
        if (month!=null){
            String firstDay = month.toString();//每月的第一天
            String lastDay = DateUtils.getLastDay(firstDay);//每月最后一天

            queryWrapper.between("submit_time",firstDay,lastDay);

            return employeeLeaveMapper.selectPage(iPage,queryWrapper);
        }else {

            return employeeLeaveMapper.selectPage(iPage,queryWrapper);
        }
    }

    /**
     * 员工撤销请假
     * @param id 员工请假id
     */
    @Override
    public void cancelLeave(Integer id) {
        employeeLeaveMapper.deleteById(id);
    }

    /**
     * 管理员候补员工请假记录
     * @param adminId 管理员ID
     * @param employeeLeave 员工请假记录对象
     */
    @Override
    public void addLeave(Integer adminId,EmployeeLeave employeeLeave) {

        Admin admin = adminMapper.selectById(adminId);
        employeeLeave.setApprover(admin.getUsername());
        employeeLeave.setStatus("同意");//直接同意

        //获取请假的开始时间和结束时间，并计算请假的天数。
        Date startTime = employeeLeave.getStartTime();
        Date endTime = employeeLeave.getEndTime();

        Integer leaveDay = DateUtils.getLeaveDay(startTime, endTime);
        employeeLeave.setDay(leaveDay);//算出请假的天数
        employeeLeave.setSubmitTime(new java.util.Date());
        employeeLeaveMapper.insert(employeeLeave);

        Long employeeId = employeeLeave.getEmployeeId();
        Calendar calendar =Calendar.getInstance();//创建一个日历对象
        //将开始时间设置为日历的初始时间
        calendar.setTime(startTime);
        //创建一个日期列表，将开始时间添加到列表中
        List<Date> dateList = new ArrayList<>();
        dateList.add(startTime);

        for (int i = 1; i < leaveDay; i++) {
            calendar.add(Calendar.DAY_OF_WEEK,1);
            Date day = new Date(calendar.getTime().getTime());
            dateList.add(day);
        }
        for (Date day : dateList) {
            LambdaQueryWrapper<OnDuty> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(OnDuty::getDay, day);
            queryWrapper.eq(OnDuty::getEmployeeId,employeeId);
            //查询该员工在该天是否有考勤记录。
            OnDuty onDutySelect = onDutyMapper.selectOne(queryWrapper);
            if (onDutySelect != null) {//(既打卡了，也请假了，中途请假)
                //如果找到了考勤记录，将其状态设置为 "请假"，并更新到数据库中。
                onDutySelect.setStatus("请假");
                onDutyMapper.updateById(onDutySelect);
            }else {//(没有打卡，直接请假了)
                //否则创建一个新的考勤记录，
                // 并设置为 "请假"，然后插入到数据库中。
                OnDuty onDuty = new OnDuty();
                onDuty.setEmployeeId(employeeLeave.getEmployeeId());
                onDuty.setDepartmentId(employeeLeave.getDepartmentId());
                onDuty.setDay(day);
                onDuty.setStatus("请假");
                onDutyMapper.insert(onDuty);
            }
        }
    }
}
